////////////////////////////////////////////////////////////////////////////
//
//  Crytek Engine Source File.
//  Copyright (C), Crytek Studios, 2002.
// -------------------------------------------------------------------------
//  File name:   terrainpainterpanel.cpp
//  Version:     v1.00
//  Created:     25/10/2002 by Timur.
//  Compilers:   Visual Studio.NET
//  Description: 
// -------------------------------------------------------------------------
//  History:
//
////////////////////////////////////////////////////////////////////////////


#include "stdafx.h"
#include "TerrainPainterPanel.h"
#include "TerrainTexturePainter.h"

#include "CryEditDoc.h"
#include ".\Terrain\Layer.h"
#include ".\terrainpainterpanel.h"

#include "Terrain/TerrainManager.h"

/////////////////////////////////////////////////////////////////////////////
// CTerrainPainterPanel dialog


CTerrainPainterPanel::CTerrainPainterPanel(CTerrainTexturePainter *tool,CWnd* pParent /*=NULL*/)
	: CXTResizeDialog(CTerrainPainterPanel::IDD, pParent)
{
	//{{AFX_DATA_INIT(CTerrainPainterPanel)
	//}}AFX_DATA_INIT

	Create( IDD,pParent );

	assert( tool != 0 );
	m_tool = tool;

	m_bIgnoreNotify = false;
	GetIEditor()->RegisterNotifyListener(this);
}

CTerrainPainterPanel::~CTerrainPainterPanel()
{
	GetIEditor()->UnregisterNotifyListener(this);
}

void CTerrainPainterPanel::DoDataExchange(CDataExchange* pDX)
{
	CXTResizeDialog::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CTerrainPainterPanel)
	DDX_Control(pDX, IDC_BRUSH_MASKLAYERID, m_MaskLayerId);
	DDX_Control(pDX, IDC_BRUSH_HARDNESS_SLIDER, m_hardnessSlider);
	DDX_Control(pDX, IDC_BRUSH_RADIUS_SLIDER, m_radiusSlider);
	DDX_Control(pDX, IDC_LAYERS, m_layers);
	DDX_Control(pDX, IDC_PAINT_DETAILLAYER, m_optDetailLayer);
	DDX_Control(pDX, IDC_PAINT_MASKBYLAYERSETTINGS, m_MaskLayerSettings);
	DDX_Control(pDX, IDC_TERRAINPAINTER_COLOR, m_SolidColor);
	DDX_Control(pDX, IDC_BRUSH_BRIGHTNESS_SLIDER, m_BrightnessSlider);
	DDX_Control(pDX, IDC_BRUSH_SETTOLAYER, m_ApplyButton);
	DDX_Control(pDX, IDC_TERRAINPAINTER_RESETBRIGHTNESS, m_ResetButton);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CTerrainPainterPanel, CXTResizeDialog)
	ON_WM_HSCROLL()
	//{{AFX_MSG_MAP(CTerrainPainterPanel)
	ON_EN_UPDATE(IDC_BRUSH_RADIUS, UpdateTextureBrushSettings)

	ON_LBN_SELCHANGE(IDC_LAYERS, SetLayerMaskSettingsToLayer)
	ON_CBN_SELENDOK(IDC_BRUSH_MASKLAYERID, UpdateTextureBrushSettings)
	ON_EN_UPDATE(IDC_BRUSH_HARDNESS, UpdateTextureBrushSettings)
	ON_EN_UPDATE(IDC_NOISE_SCALE, UpdateTextureBrushSettings)
	ON_EN_UPDATE(IDC_NOISE_FREQ, UpdateTextureBrushSettings)
	ON_CPN_XT_SELENDOK(IDC_TERRAINPAINTER_COLOR, UpdateTextureBrushSettings)

	ON_BN_CLICKED(IDC_PAINT_DETAILLAYER, UpdateTextureBrushSettings)
	ON_BN_CLICKED(IDC_PAINT_MASKBYLAYERSETTINGS, UpdateTextureBrushSettings)
	ON_BN_CLICKED(IDC_TERRAINPAINTER_RESETBRIGHTNESS,OnBrushResetBrightness)

	ON_EN_UPDATE(IDC_BRUSH_LAYER_ALTMIN, GetLayerMaskSettingsFromLayer)
	ON_EN_UPDATE(IDC_BRUSH_LAYER_ALTMAX, GetLayerMaskSettingsFromLayer)
	ON_EN_UPDATE(IDC_BRUSH_LAYER_SLOPEMIN, GetLayerMaskSettingsFromLayer)
	ON_EN_UPDATE(IDC_BRUSH_LAYER_SLOPEMAX, GetLayerMaskSettingsFromLayer)

	//}}AFX_MSG_MAP

	ON_BN_CLICKED(IDC_BRUSH_SETTOLAYER, &CTerrainPainterPanel::OnBnClickedBrushSettolayer)
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CTerrainPainterPanel message handlers

BOOL CTerrainPainterPanel::OnInitDialog() 
{
	CXTResizeDialog::OnInitDialog();
	
	m_brushRadius.Create( this,IDC_BRUSH_RADIUS );
	m_brushRadius.SetRange( 0,32 );
	
	m_brushHardness.Create( this,IDC_BRUSH_HARDNESS );
	m_brushHardness.SetRange( 0,1 );

	m_layerAltMin.Create( this,IDC_BRUSH_LAYER_ALTMIN );
	m_layerAltMin.SetRange( 0,1024 );
	m_layerAltMax.Create( this,IDC_BRUSH_LAYER_ALTMAX );
	m_layerAltMax.SetRange( 0,4096 );
	m_layerSlopeMin.Create( this,IDC_BRUSH_LAYER_SLOPEMIN );
	m_layerSlopeMin.SetRange( 0,90 );
	m_layerSlopeMax.Create( this,IDC_BRUSH_LAYER_SLOPEMAX );
	m_layerSlopeMax.SetRange( 0,90 );

	float fMax=1000;
	m_radiusSlider.SetRange( 1,100 * log10(fMax) );	

	m_hardnessSlider.SetRange( 0,100 );
	m_BrightnessSlider.SetRange( 0,512 );

	m_SolidColor.SetColor(RGB(255,255,255));
	m_SolidColor.SetWindowText("");

	// Fill layers.
	ReloadLayers();

	SetResize(IDC_BRUSH_RADIUS_SLIDER, SZ_HORRESIZE(1.0f));
	SetResize(IDC_BRUSH_HARDNESS_SLIDER, SZ_HORRESIZE(1.0f));
	SetResize(IDC_BRUSH_BRIGHTNESS_SLIDER, SZ_HORRESIZE(1.0f));
	SetResize(IDC_TERRAINPAINTER_RESETBRIGHTNESS, SZ_HORRESIZE(0.5f));
	SetResize(IDC_BRUSH_SETTOLAYER, CXTResizeRect(0.5f, 0.0f, 1.0f, 0.0f));
	SetResize(IDC_TERRAINPAINTER_COLOR, SZ_HORRESIZE(1.0f));
	SetResize(IDC_FILTER_GRPRECT, SZ_HORRESIZE(1.0f));
	SetResize(IDC_LAYER_GRPRECT, SZ_HORRESIZE(1.0f));
	SetResize(IDC_BRUSH_GRPRECT, SZ_HORRESIZE(1.0f));
	SetResize(IDC_LAYERS, SZ_HORRESIZE(1.0f));

	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::SetBrush( CTextureBrush &br )
{
	m_brushRadius.SetRange( br.minRadius,br.maxRadius );
	m_brushRadius.SetValue( br.radius );
	m_brushHardness.SetValue( br.hardness );
	m_optDetailLayer.SetCheck( (br.bDetailLayer)?BST_CHECKED:BST_UNCHECKED );
	m_MaskLayerSettings.SetCheck( (br.bMaskByLayerSettings)?BST_CHECKED:BST_UNCHECKED );
	m_SolidColor.SetColor(br.m_cFilterColor.pack_abgr8888()&0xffffff);

	m_radiusSlider.SetPos( log10(br.radius)*100.0f );
	m_BrightnessSlider.SetPos( br.m_fBrightness*255.0f );
	m_hardnessSlider.SetPos( br.hardness*100.0f );
	
	m_optDetailLayer.EnableWindow(br.m_dwMaskLayerId==0xffffffff);
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::OnHScroll( UINT nSBCode,UINT nPos,CScrollBar* pScrollBar )
{
	CTextureBrush br;
	m_tool->GetBrush(br);
	br.hardness = (float)m_hardnessSlider.GetPos()/100.0f;
	br.m_fBrightness = m_BrightnessSlider.GetPos()/255.0f;
	br.radius =  pow(10.0f,m_radiusSlider.GetPos()/100.0f);
	SetBrush( br );
	m_tool->SetBrush(br);
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::SelectLayer( const CLayer *pLayer )
{
	for (int i = 0; i < CTerrainManager::GetTerrainManager().GetLayerCount(); i++)
	{
		CLayer *pLayerIt = CTerrainManager::GetTerrainManager().GetLayer(i);
		pLayerIt->SetSelected(pLayerIt==pLayer);
	}

	ReloadLayers();
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::ReloadLayers()
{
	CLayer *pSelectedLayer=0;
	int nSelectedItem=0;
	m_layers.ResetContent();
	m_MaskLayerId.ResetContent();
	m_MaskLayerId.AddString("<none>");
	for (int i = 0; i < CTerrainManager::GetTerrainManager().GetLayerCount(); i++)
	{
		CLayer *pLayer = CTerrainManager::GetTerrainManager().GetLayer(i);

		int index = m_layers.AddString( pLayer->GetLayerName() );
		m_layers.SetItemDataPtr(index, pLayer);
		m_MaskLayerId.AddString( pLayer->GetLayerName() );
		if (pLayer->IsSelected())
		{
			pSelectedLayer=pLayer;
			nSelectedItem = index;
		}
	}
	m_MaskLayerId.SelectString( -1,"<none>" );

	CTextureBrush br;
	m_tool->GetBrush(br);
	br.m_dwMaskLayerId=0xffffffff;
	m_tool->SetBrush(br);
	m_layers.SelectString( nSelectedItem-1, pSelectedLayer?pSelectedLayer->GetLayerName():"" );

	SetLayerMaskSettingsToLayer();
}

//////////////////////////////////////////////////////////////////////////
CLayer* CTerrainPainterPanel::GetSelectedLayer()
{
	int curSel = m_layers.GetCurSel();
	if (curSel < 0)
		return 0;
	return (CLayer*) m_layers.GetItemDataPtr(curSel);
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::OnBrushResetBrightness()
{
	m_BrightnessSlider.SetPos(255);

	CTextureBrush br;
	m_tool->GetBrush(br);
	br.m_fBrightness = m_BrightnessSlider.GetPos()/255.0f;
	SetBrush( br );
	m_tool->SetBrush(br);
}


//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::UpdateTextureBrushSettings()
{
	CTextureBrush br;
	m_tool->GetBrush(br);

	br.bDetailLayer = m_optDetailLayer.GetCheck();
	br.bMaskByLayerSettings = m_MaskLayerSettings.GetCheck();
	br.radius = m_brushRadius.GetValue();
	br.hardness = m_brushHardness.GetValue();
	br.m_cFilterColor = ColorF((unsigned int)m_SolidColor.GetColor());

	br.m_dwMaskLayerId=0xffffffff;

	{
		int sel = m_MaskLayerId.GetCurSel();
		if (sel != LB_ERR)
		{
			CString selStr;
			m_MaskLayerId.GetLBText(sel,selStr);
			
			CLayer *pLayer = CTerrainManager::GetTerrainManager().FindLayer(selStr);

			if(pLayer)
			{
				br.m_dwMaskLayerId=pLayer->GetOrRequestLayerId();
//				pLayer->m_cLayerFilterColor=br.m_cFilterColor;
//				pLayer->m_fLayerBrightness=br.m_fBrightness;
			}
		}
	}
	
	SetBrush( br );

	m_tool->SetBrush(br);
}



void CTerrainPainterPanel::SetLayerMaskSettingsToLayer()
{
	CLayer* pLayer = GetSelectedLayer();

	m_layerAltMin.EnableWindow(pLayer!=0);
	m_layerAltMax.EnableWindow(pLayer!=0);
	m_layerSlopeMin.EnableWindow(pLayer!=0);
	m_layerSlopeMax.EnableWindow(pLayer!=0);

	if(pLayer)
	{
		m_layerAltMin.SetValue( pLayer->GetLayerStart() );
		m_layerAltMax.SetValue( pLayer->GetLayerEnd() );
		m_layerSlopeMin.SetValue( pLayer->GetLayerMinSlopeAngle() );
		m_layerSlopeMax.SetValue( pLayer->GetLayerMaxSlopeAngle() );

		CTextureBrush br;
		m_tool->GetBrush(br);
		br.m_cFilterColor=pLayer->m_cLayerFilterColor;
		br.m_fBrightness=pLayer->m_fLayerBrightness;
		m_tool->SetBrush(br);

		m_SolidColor.SetColor(br.m_cFilterColor.pack_abgr8888()&0xffffff);
		m_BrightnessSlider.SetPos(br.m_fBrightness*255.0f);
	}
	else
	{
		m_layerAltMin.SetValue(0);
		m_layerAltMax.SetValue(255);
		m_layerSlopeMin.SetValue(0);
		m_layerSlopeMax.SetValue(90);
	}

	CCryEditDoc *pDoc = GetIEditor()->GetDocument();
	for (int i = 0; i < CTerrainManager::GetTerrainManager().GetLayerCount(); i++)
		CTerrainManager::GetTerrainManager().GetLayer(i)->SetSelected(false);
	if (pLayer)
		pLayer->SetSelected(true);

	m_bIgnoreNotify = true;
	GetIEditor()->Notify(eNotify_OnSelectionChange);
	m_bIgnoreNotify = false;
}



void CTerrainPainterPanel::GetLayerMaskSettingsFromLayer()
{
	CLayer* pLayer = GetSelectedLayer();

	if(pLayer)
	{
		pLayer->SetLayerStart(m_layerAltMin.GetValue());
		pLayer->SetLayerEnd(m_layerAltMax.GetValue());
		pLayer->SetLayerMinSlopeAngle(m_layerSlopeMin.GetValue());
		pLayer->SetLayerMaxSlopeAngle(m_layerSlopeMax.GetValue());
		GetIEditor()->GetDocument()->SetModifiedFlag(TRUE);
		GetIEditor()->SetModifiedModule(eModifiedTerrain);
	}

	m_bIgnoreNotify = true;
	GetIEditor()->Notify(eNotify_OnInvalidateControls);
	m_bIgnoreNotify = false;
}




void CTerrainPainterPanel::OnBnClickedBrushSettolayer()
{
	CLayer* pLayer = GetSelectedLayer();

	if(!pLayer)
		return;

	CTextureBrush br;
	m_tool->GetBrush(br);

	pLayer->m_cLayerFilterColor=br.m_cFilterColor;
	pLayer->m_fLayerBrightness=br.m_fBrightness;

	m_bIgnoreNotify = true;
	GetIEditor()->Notify(eNotify_OnInvalidateControls);
	m_bIgnoreNotify = false;
}


/*
//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::OnExport()
{
	m_tool->ImportExport(false, false);
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::OnImport()
{
	m_tool->ImportExport(true, false);
}

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::OnFileBrowse()
{
	gSettings.BrowseTerrainTexture();
	GetDlgItem(IDC_FILE)->SetWindowText( gSettings.terrainTextureExport);
}
*/

//////////////////////////////////////////////////////////////////////////
void CTerrainPainterPanel::OnEditorNotifyEvent( EEditorNotifyEvent event )
{
	if(m_bIgnoreNotify)
		return;
	switch (event)
	{
	case eNotify_OnInvalidateControls:
		ReloadLayers();
		break;
	case eNotify_OnSelectionChange:
		{
			CCryEditDoc *pDoc = GetIEditor()->GetDocument();
			for (int i = 0; i < CTerrainManager::GetTerrainManager().GetLayerCount(); i++)
			{
				if(CTerrainManager::GetTerrainManager().GetLayer(i)->IsSelected())
				{
					SelectLayer( CTerrainManager::GetTerrainManager().GetLayer(i) );
					break;
				}
			}
		}
		break;
	}
}
